﻿@using System.Threading
@{
    Layout = null;
}
<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>Abp</title>
    <link rel="shortcut icon" type="image/ico" href="/favicon.ico" />
    <script type="text/javascript" src="http://demo.js.jdk5.com/IDValidator/GB2260.js" charset="utf-8"></script>
    <script type="text/javascript">
        function IDValidator() {
            var param = {
                error: {
                    longNumber: '长数字存在精度问题，请使用字符串传值！ Long number is not allowed, because the precision of the Number In JavaScript.'
                }
            };
            var util = {
                checkArg: function (id) {
                    var argType = (typeof id);

                    switch (argType) {
                        case 'number':
                            // long number not allowed
                            id = id.toString();
                            if (id.length > 15) {
                                this.error(param.error.longNumber);
                                return false;
                            }
                            break;
                        case 'string':
                            break;
                        default:
                            return false;
                    }
                    id = id.toUpperCase();
                    var code = null;
                    if (id.length === 18) {
                        // 18位
                        code = {
                            body: id.slice(0, 17),
                            checkBit: id.slice(-1),
                            type: 18
                        };
                    } else if (id.length === 15) {
                        // 15位
                        code = {
                            body: id,
                            type: 15
                        };
                    } else {
                        return false;
                    }
                    return code;
                }
                // 地址码检查
                ,
                checkAddr: function (addr, GB2260) {
                    var addrInfo = this.getAddrInfo(addr, GB2260);
                    return (addrInfo === false ? false : true);
                }
                // 取得地址码信息
                ,
                getAddrInfo: function (addr, GB2260) {
                    GB2260 = GB2260 || null;
                    // 查询GB/T2260,没有引入GB2260时略过
                    if (GB2260 === null) {
                        return addr;
                    }
                    if (!GB2260.hasOwnProperty(addr)) {
                        // 考虑标准不全的情况，搜索不到时向上搜索
                        var tmpAddr;
                        tmpAddr = addr.slice(0, 4) + '00';
                        if (!GB2260.hasOwnProperty(tmpAddr)) {
                            tmpAddr = addr.slice(0, 2) + '0000';
                            if (!GB2260.hasOwnProperty(tmpAddr)) {
                                return false;
                            } else {
                                return GB2260[tmpAddr] + '未知地区';
                            }
                        } else {
                            return GB2260[tmpAddr] + '未知地区';
                        }
                    } else {
                        return GB2260[addr];
                    }
                }
                // 生日码检查
                ,
                checkBirth: function (birth) {
                    var year, month, day;
                    if (birth.length == 8) {
                        year = parseInt(birth.slice(0, 4), 10);
                        month = parseInt(birth.slice(4, 6), 10);
                        day = parseInt(birth.slice(-2), 10);
                    } else if (birth.length == 6) {
                        year = parseInt('19' + birth.slice(0, 2), 10);
                        month = parseInt(birth.slice(2, 4), 10);
                        day = parseInt(birth.slice(-2), 10);
                    } else {
                        return false;
                    }
                    // TODO 是否需要判断年份
                    /*
                     * if( year<1800 ){ return false; }
                     */
                    // TODO 按月份检测
                    if (month > 12 || month === 0 || day > 31 || day === 0) {
                        return false;
                    }

                    return true;
                }
                // 顺序码检查
                ,
                checkOrder: function (order) {
                    // 暂无需检测

                    return true;
                }
                // 加权
                ,
                weight: function (t) {
                    return Math.pow(2, t - 1) % 11;
                }
                // 随机整数
                ,
                rand: function (max, min) {
                    min = min || 1;
                    return Math.round(Math.random() * (max - min)) + min;
                }
                // 数字补位
                ,
                str_pad: function (str, len, chr, right) {
                    str = str.toString();
                    len = len || 2;
                    chr = chr || '0';
                    right = right || false;
                    if (str.length >= len) {
                        return str;
                    } else {
                        for (var i = 0, j = len - str.length; i < j; i++) {
                            if (right) {
                                str = str + chr;
                            } else {
                                str = chr + str;
                            }
                        }
                        return str;
                    }
                }
                // 抛错
                ,
                error: function (msg) {
                    var e = new Error();
                    e.message = 'IDValidator: ' + msg;
                    throw e;
                }
            };
            var _IDValidator = function (GB2260) {
                if (typeof GB2260 !== "undefined") {
                    this.GB2260 = GB2260;
                }
                // 建立cache
                this.cache = {};
            };
            _IDValidator.prototype = {
                isValid: function (id) {
                    var GB2260 = this.GB2260 || null;
                    var code = util.checkArg(id);
                    if (code === false) {
                        return false;
                    }
                    // 查询cache
                    if (this.cache.hasOwnProperty(id)
                            && typeof this.cache[id].valid !== 'undefined') {
                        return this.cache[id].valid;
                    } else {
                        if (!this.cache.hasOwnProperty(id)) {
                            this.cache[id] = {};
                        }
                    }

                    var addr = code.body.slice(0, 6);
                    var birth = (code.type === 18 ? code.body.slice(6, 14) : code.body
                            .slice(6, 12));
                    var order = code.body.slice(-3);

                    if (!(util.checkAddr(addr, GB2260) && util.checkBirth(birth) && util
                            .checkOrder(order))) {
                        this.cache[id].valid = false;
                        return false;
                    }

                    // 15位不含校验码，到此已结束
                    if (code.type === 15) {
                        this.cache[id].valid = true;
                        return true;
                    }

                    /* 校验位部分 */

                    // 位置加权
                    var posWeight = [];
                    for (var i = 18; i > 1; i--) {
                        var wei = util.weight(i);
                        posWeight[i] = wei;
                    }

                    // 累加body部分与位置加权的积
                    var bodySum = 0;
                    var bodyArr = code.body.split('');
                    for (var j = 0; j < bodyArr.length; j++) {
                        bodySum += (parseInt(bodyArr[j], 10) * posWeight[18 - j]);
                    }

                    // 得出校验码
                    var checkBit = 12 - (bodySum % 11);
                    if (checkBit == 10) {
                        checkBit = 'X';
                    } else if (checkBit > 10) {
                        checkBit = checkBit % 11;
                    }
                    checkBit = (typeof checkBit === 'number' ? checkBit.toString()
                            : checkBit);

                    // 检查校验码
                    if (checkBit !== code.checkBit) {
                        this.cache[id].valid = false;
                        return false;
                    } else {
                        this.cache[id].valid = true;
                        return true;
                    }

                }

                // 分析详细信息
                ,
                getInfo: function (id) {
                    var GB2260 = this.GB2260 || null;
                    // 号码必须有效
                    if (this.isValid(id) === false) {
                        return false;
                    }
                    // TODO 复用此部分
                    var code = util.checkArg(id);

                    // 查询cache
                    // 到此时通过isValid已经有了cache记录
                    if (typeof this.cache[id].info !== 'undefined') {
                        return this.cache[id].info;
                    }

                    var addr = code.body.slice(0, 6);
                    var birth = (code.type === 18 ? code.body.slice(6, 14) : code.body
                            .slice(6, 12));
                    var order = code.body.slice(-3);

                    var info = {};
                    info.addrCode = addr;
                    if (GB2260 !== null) {
                        info.addr = util.getAddrInfo(addr, GB2260);
                    }
                    info.birth = (code.type === 18 ? (([birth.slice(0, 4),
                            birth.slice(4, 6), birth.slice(-2)]).join('-')) : ([
                            '19' + birth.slice(0, 2), birth.slice(2, 4),
                            birth.slice(-2)]).join('-'));
                    info.sex = (order % 2 === 0 ? 0 : 1);
                    info.length = code.type;
                    if (code.type === 18) {
                        info.checkBit = code.checkBit;
                    }

                    // 记录cache
                    this.cache[id].info = info;

                    return info;
                }

                // 仿造一个号
                ,
                makeID: function (isFifteen) {
                    var GB2260 = this.GB2260 || null;

                    // 地址码
                    var addr = null;
                    if (GB2260 !== null) {
                        var loopCnt = 0;
                        while (addr === null) {
                            // 防止死循环
                            if (loopCnt > 10) {
                                addr = 110101;
                                break;
                            }
                            var prov = util.str_pad(util.rand(50), 2, '0');
                            var city = util.str_pad(util.rand(20), 2, '0');
                            var area = util.str_pad(util.rand(20), 2, '0');
                            var addrTest = [prov, city, area].join('');
                            if (GB2260[addrTest]) {
                                addr = addrTest;
                                break;
                            }
                        }
                    } else {
                        addr = 110101;
                    }

                    // 出生年
                    var yr = util.str_pad(util.rand(99, 50), 2, '0');
                    var mo = util.str_pad(util.rand(12, 1), 2, '0');
                    var da = util.str_pad(util.rand(28, 1), 2, '0');
                    if (isFifteen) {
                        return addr + yr + mo + da
                                + util.str_pad(util.rand(999, 1), 3, '1');
                    }

                    yr = '19' + yr;
                    var body = addr + yr + mo + da
                            + util.str_pad(util.rand(999, 1), 3, '1');

                    // 位置加权
                    var posWeight = [];
                    for (var i = 18; i > 1; i--) {
                        var wei = util.weight(i);
                        posWeight[i] = wei;
                    }

                    // 累加body部分与位置加权的积
                    var bodySum = 0;
                    var bodyArr = body.split('');
                    for (var j = 0; j < bodyArr.length; j++) {
                        bodySum += (parseInt(bodyArr[j], 10) * posWeight[18 - j]);
                    }

                    // 得出校验码
                    var checkBit = 12 - (bodySum % 11);
                    if (checkBit == 10) {
                        checkBit = 'X';
                    } else if (checkBit > 10) {
                        checkBit = checkBit % 11;
                    }
                    checkBit = (typeof checkBit === 'number' ? checkBit.toString()
                            : checkBit);

                    return (body + checkBit);
                }

            };// _IDValidator
            GB2260 = GB2260 == null ? "" : GB2260;
            return new _IDValidator(GB2260);
        }

        //新建普通实例
        var Validator = new IDValidator();

        //验证号码是否合法，合法返回true，不合法返回false
        var isValid = Validator.isValid('420983199108286418');

        //号码合法时返回分析信息（地区、出生日期、性别、校验位），不合法返回false
        var userInfo = Validator.getInfo('420983199108286418');

        document.write(isValid);
        document.write(JSON.stringify(userInfo));
    </script>
</head>
<body>
</body>
</html>